﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;

namespace DARE
{
    /// <summary>
    /// This represents the main abstract class for the scrollbars.
    /// </summary>
    /// <seealso cref="CHorizontalSelector"/>
    /// <seealso cref="CVerticalSelector"/>
    [AttrTypeDependentSerializable(typeof(CSelectorData))]
    public class CSelector: CWidget
    {
        #region fields

        protected List<CWidget> m_list;
        protected CWidget m_selected;
        protected int m_selectedIndex;

        protected CButton m_nextButton;
        protected CButton m_prevButton;

        protected Rectangle m_bodyRect;
        protected bool m_loopEnabled;

        protected bool m_displayNumPage = false;
        protected Vector2 m_numPagePos;
        protected Color m_numPageColor;

        #endregion

        #region properties

        public bool AdjustSize { get; set; }

        /// <summary>
        /// Enables/Disables the loop state.
        /// If this value is set to true, when we reaches the last item in the selector and we click the
        /// more button, it will go back to the first item.
        /// </summary>
        /// <summary>
        /// Enables/Disables the loop state.
        /// If this value is set to true, when we reaches the last item in the selector and we click the
        /// more button, it will go back to the first item.
        /// </summary>
        public bool EnableLoop { get { return m_loopEnabled; } set { m_loopEnabled = value; } }

        /// <summary>
        /// Gets/Sets the index of the selected item.
        /// </summary>
        public int SelectedIndex { get { return m_selectedIndex; } set { m_selectedIndex = value; } }

        /// <summary>
        /// Gets the current displayed widget
        /// </summary>
        public CWidget CurrentWidgetDisplayed { get { return m_list[m_selectedIndex]; } }

        /// <summary>
        /// Displays or not the number of the current page
        /// </summary>
        public bool DisplayNumPage { get { return m_displayNumPage; } set { m_displayNumPage = value; } }

        /// <summary>
        /// Gets/Sets the color of the number of the current page displayed
        /// </summary>
        public Color NumPageColor { get { return m_numPageColor; } set { m_numPageColor = value; } }

        /// <summary>
        /// If the value is between 0 and 1, the size is a percentage of the size of the parent
        /// (if the parent is null, the value is a percentage of the window).
        /// Else, the value is absolute.
        /// </summary>
        public override Vector2 Size
        {
            get
            {
                return base.Size;
            }
            set
            {
                base.Size = value;
                Actualize();
            }
        }

        /// <summary>
        /// If the value is between 0 and 1, the position is a percentage of the size of the parent
        /// (if the parent is null, the value is a percentage of the window).
        /// The value is relative to its parent.
        /// </summary>
        public override Vector2 Position
        {
            get
            {
                return base.Position;
            }
            set
            {
                base.Position = value;
                Actualize();
            }
        }

        /// <summary>
        /// Gets/Sets the rectangle where the widget will be draw.
        /// This value is automatically set when the position and/or the size are set.
        /// If you plan to use a different rectangle than the one automatically created,
        /// we recommand you to use the UseDrawableRect and DrawableRect properties.
        /// </summary>
        /// <seealso cref="UseDrawableRect"/>
        /// <seealso cref="DrawableRect"/>
        public override Rectangle Rect
        {
            get
            {
                return base.Rect;
            }
            set
            {
                base.Rect = value;
                Actualize();
            }
        }

        #endregion

        #region ctor

        public CSelector(CHUDSystem hud, CWidget parent, string name)
            : base(hud, parent, name)
        {
            m_list = new List<CWidget>();
            m_selected = null;

            m_nextButton = new CButton(hud, this, name + "_nextButton");
            m_nextButton.Size = new Vector2(15, 15);
            m_nextButton.OnRelease += next;

            m_prevButton = new CButton(hud, this, name + "_prevButton");
            m_prevButton.Size = new Vector2(15, 15);
            m_prevButton.OnRelease += prev;

            m_bodyRect = m_rect;
        }

        #endregion

        #region actualize

        /// <summary>
        /// Actualizes the widget.
        /// If anything has changed, it will allow this widget to get back its parameters.
        /// For example, if the size of the widget is a percentage of the size of its parent,
        /// if the parent's size changes, it will recalculate the good size of this widget.
        /// (This method is called automatically but you can force a new actualization).
        /// </summary>
        public override void Actualize()
        {
            base.Actualize();
            m_bodyRect = m_rect;
            m_nextButton.Size = new Vector2(15, 15);

            m_prevButton.Size = new Vector2(15, 15);
            if (m_selected != null)
                m_selected.Hide();
            if (m_list.Count > 0)
                m_selected = m_list[m_selectedIndex];
            if (m_selected != null)
                m_selected.Show();
            if (m_selectedIndex == 0 && !m_loopEnabled)
                m_prevButton.Hide();
            else
                m_prevButton.Show();
            if (m_selectedIndex == m_list.Count - 1 && !m_loopEnabled)
                m_nextButton.Hide();
            else
                m_nextButton.Show();
        }

        #endregion

        #region event

        /// <summary>
        /// Method called whenever we click on the next button
        /// </summary>
        public void next(CWidget sender)
        {
            if (CDare.Instance.InputMgr.Mouse.ButtonReleasedEvent.First() == CMouse.EButton.LEFT)
            {
                if (m_list.Count <= 0)
                    return;
                ++m_selectedIndex;
                if (m_selectedIndex >= m_list.Count)
                {
                    if (!m_loopEnabled)
                        --m_selectedIndex;
                    else
                        m_selectedIndex = 0;
                }
                Actualize();
            }
        }

        /// <summary>
        /// Method called whenever we click on the prev button
        /// </summary>
        public void prev(CWidget sender)
        {
            if (CDare.Instance.InputMgr.Mouse.ButtonReleasedEvent.First() == CMouse.EButton.LEFT)
            {
                if (m_list.Count <= 0)
                    return;
                --m_selectedIndex;
                if (m_selectedIndex < 0)
                {
                    if (!m_loopEnabled)
                        ++m_selectedIndex;
                    else
                        m_selectedIndex = m_list.Count - 1;
                }
                Actualize();
            }
        }

        #endregion
    }
}
